package com.ruoyi.plus.utils.sms.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.plus.constants.PlusConstants;
import com.ruoyi.plus.utils.sms.ISmsService;
import com.ruoyi.plus.utils.sms.domain.CheckCodeModel;
import com.ruoyi.plus.utils.sms.domain.SmsAliYun;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author liqingsong
 */
@Service
@Slf4j
public class SmsServiceImpl implements ISmsService {

    private final RedisTemplate redisTemplate = SpringUtils.getBean("redisTemplate");


    @Autowired
    private SmsAliYun smsAliYun;

    @Override
    public CheckCodeModel checkCode(String phoneNumbers, String code) {
        CheckCodeModel result = new CheckCodeModel().setCheckResult(false).setCheckMsg("校验验证码失败!");
        String code1 = (String) redisTemplate.opsForValue().get(PlusConstants.SMS_CODE_KEY + phoneNumbers);
        if (StringUtils.isEmpty(code1)) {
            //验证码失效
            return result.setCheckResult(false).setCheckMsg("验证码失效");
        }
        if (code.equals(code1)) {
            redisTemplate.delete(PlusConstants.SMS_CODE_KEY + phoneNumbers);
            return result.setCheckResult(true).setCheckMsg("验证码校验成功!");
        }
        //验证码错误
        return result.setCheckResult(false).setCheckMsg("验证码错误!");
    }

    @Override
    public String genCode(String phoneNumbers) {
        String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        redisTemplate.opsForValue().set(PlusConstants.SMS_CODE_KEY + phoneNumbers, code, 5L, TimeUnit.MINUTES);
        return code;
    }

    @Async
    @Override
    public Future<Boolean> sendCode(String phoneNumbers, String code) {
        return new AsyncResult<>(this.sendCodeByAliYun(phoneNumbers, code));
    }


    private Boolean sendCodeByAliYun(String phoneNumbers, String code) {
        DefaultProfile profile = DefaultProfile.getProfile(smsAliYun.getRegionId(), smsAliYun.getAccessKeyId(), smsAliYun.getAccessSecret());
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", smsAliYun.getRegionId());
        request.putQueryParameter("PhoneNumbers", phoneNumbers);
        request.putQueryParameter("SignName", smsAliYun.getSignName());
        request.putQueryParameter("TemplateCode", smsAliYun.getTemplateCode());
        request.putQueryParameter("TemplateParam", "{\"code\":" + code + "}");
        try {
            CommonResponse response = client.getCommonResponse(request);
            JSONObject resultObj = JSON.parseObject(response.getData());
            String resultCode = resultObj.getString("Code");
            if ("OK".equals(resultCode)) {
                log.info("------调用阿里接口成功:{} {}--------", phoneNumbers, code);
                return true;
            } else {
                log.error("------调用阿里接口失败:{} {} {}--------", phoneNumbers, code, response.getData());
            }
            return false;
        } catch (ServerException e) {
            log.error("发送短信失败：", e);
            return false;
        } catch (ClientException e) {
            log.error("发送短信失败：", e);
            return false;
        } catch (Exception e) {
            log.error("发送短信失败：", e);
            return false;
        }
    }

}
